Estaciones hidrometeorológicas
Introducción
En este cuadernillo (Notebook) aprenderemos:
Introduccion a la red de monitoreo del IDEAM
Cátalogo de estaciones de IDEAM
Consulta de datos usando la plataforma datosabiertos.gov.co
Consulta de datos de temperatura y precipitación
Otros datos disponibles
Prerequisitos
Conceptos |
Importancia |
Notas |
|---|---|---|
Necesario |
lectura de datos tabulares |
|
Necesario |
Entender estampas de tiempo |
|
Necesario |
Entender estampas de tiempo |
|
Útil |
Mapas interactivos |
Tiempo de aprendizaje: 30 minutos
1. Catalogo nacional de estaciones de IDEAM
Según el catálogo de estaciones hidrometeorológicas de IDEAM, el pais cuenta con alrededor de 4.400 estaciones de diferentes categorias. En el siguiente cuadro se resume el estado de las estaciones por categoría de acuerdo a la PQR No. 20229050190832 (Enero de 2023)
Categoria |
Activa |
Mantenimiento |
Suspendidas |
|---|---|---|---|
Limnigráfica |
287 |
109 |
106 |
Climátologica principal |
215 |
60 |
92 |
Mareográfica |
4 |
2 |
2 |
Pluviográfica |
104 |
0 |
87 |
Limnimétrica |
323 |
11 |
557 |
Climática Ordinaria |
211 |
31 |
253 |
Agrometeorológica |
51 |
4 |
57 |
Radio Sonda |
6 |
2 |
2 |
Pluviométrica |
1109 |
9 |
603 |
Meteorológica Especial |
40 |
4 |
68 |
Sinóptica Principal |
27 |
3 |
4 |
Sinóptica Secundaria |
2 |
0 |
5 |
Total |
2381 |
235 |
1866 |
Librerias
A continuación vamos a importar las librerias que utilizaremos en este cuadernillo
import pandas as pd
import cartopy.crs as ccrs
import cartopy.feature as feature
import matplotlib.pyplot as plt
2. Acceso al catalogo en bart.ideam.gov.co
El catalogo nacional de estaciones de IDEAM actualizado se encuentra disponible en el servidor Bart. Podemos leer el catálogo usando pandas.read_excel como se muestra a continuación:
df_cat = pd.read_excel('http://bart.ideam.gov.co/cneideam/CNE_IDEAM.xls')
#df_cat.head()
df_cat.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4497 entries, 0 to 4496
Data columns (total 21 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 OBJECTID 4497 non-null int64
1 CODIGO 4497 non-null int64
2 nombre 4497 non-null object
3 CATEGORIA 4497 non-null object
4 TECNOLOGIA 4497 non-null object
5 ESTADO 4497 non-null object
6 FECHA_INSTALACION 4496 non-null datetime64[ns]
7 altitud 4497 non-null int64
8 latitud 4497 non-null float64
9 longitud 4497 non-null float64
10 DEPARTAMENTO 4497 non-null object
11 MUNICIPIO 4497 non-null object
12 AREA_OPERATIVA 4497 non-null object
13 AREA_HIDROGRAFICA 4497 non-null object
14 ZONA_HIDROGRAFICA 4497 non-null object
15 observacion 1335 non-null object
16 CORRIENTE 4497 non-null object
17 FECHA_SUSPENSION 1844 non-null datetime64[ns]
18 SUBZONA_HIDROGRAFICA 4497 non-null object
19 ENTIDAD 4497 non-null object
20 subred 1143 non-null object
dtypes: datetime64[ns](2), float64(2), int64(3), object(14)
memory usage: 737.9+ KB
2.1 Mapa de estaciones
Podemos usar cartopy para hacer un mapa y visualizar las estaciones de monitoreo en el pais
fig, ax = plt.subplots(subplot_kw={"projection": ccrs.PlateCarree()}, dpi=150)
ax.coastlines()
gl = ax.gridlines(draw_labels=True, crs=ccrs.PlateCarree())
ax.scatter(df_cat['longitud'], df_cat['latitud'], transform=ccrs.PlateCarree(), s=.5)
ax.add_feature(feature.LAND)
ax.add_feature(feature.OCEAN)
ax.add_feature(feature.COASTLINE, linewidth=.5)
ax.add_feature(feature.BORDERS, linewidth=.5)
<cartopy.mpl.feature_artist.FeatureArtist at 0x7fd86562de50>
/usr/share/miniconda3/envs/atmoscol2023/lib/python3.11/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/50m_physical/ne_50m_land.zip
warnings.warn(f'Downloading: {url}', DownloadWarning)
/usr/share/miniconda3/envs/atmoscol2023/lib/python3.11/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/50m_physical/ne_50m_ocean.zip
warnings.warn(f'Downloading: {url}', DownloadWarning)
/usr/share/miniconda3/envs/atmoscol2023/lib/python3.11/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/50m_physical/ne_50m_coastline.zip
warnings.warn(f'Downloading: {url}', DownloadWarning)
/usr/share/miniconda3/envs/atmoscol2023/lib/python3.11/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/50m_cultural/ne_50m_admin_0_boundary_lines_land.zip
warnings.warn(f'Downloading: {url}', DownloadWarning)
podemos agrupar la data por área operativa, tipo de estacion, tecnologia, y otras variables
# df_grp = df_cat.groupby('AREA_OPERATIVA')
# df_grp = df_cat.groupby('TECNOLOGIA')
df_grp = df_cat.groupby('ESTADO')
fig, ax = plt.subplots(subplot_kw={"projection":ccrs.PlateCarree()}, dpi=150)
for _, group in df_grp:
ax.scatter(group['longitud'], group['latitud'], transform=ccrs.PlateCarree(), s=.5, label=_)
ax.coastlines()
gl = ax.gridlines(draw_labels=True, crs=ccrs.PlateCarree())
ax.add_feature(feature.LAND)
ax.add_feature(feature.OCEAN)
ax.add_feature(feature.COASTLINE, linewidth=.5)
ax.add_feature(feature.BORDERS, linewidth=.5)
ax.legend(fontsize=5)
<matplotlib.legend.Legend at 0x7fd86569d150>
Podemos validar el numero total de estaciones activas, en matenimiento y suspendidas de acuerdo con la información contenida en el catálogo
for grp in df_grp.groups.keys():
print(f"{grp}: {len(df_grp.get_group(grp))}")
Activa: 2202
En Mantenimiento: 429
Suspendida: 1866
2.2 Mapa de estaciones interactivo
También podemos hacer mapas interactivos usando folium
import folium
from folium import plugins
from folium.plugins import MarkerCluster
min_lon, max_lon, min_lat, max_lat = -90, -72, -1, 14
map_ = folium.Map(location=[8, -76],
zoom_start = 6,
min_lat=min_lat,
max_lat=max_lat,
min_lon=min_lon,
max_lon=max_lon,
zoom_control=False,
control_scale=True,
scrollWheelZoom=True,
width=1000,height=600)
marker_cluster = MarkerCluster(name="Estaciones").add_to(map_)
folium.TileLayer('cartodbpositron').add_to(map_)
folium.TileLayer('openstreetmap').add_to(map_)
folium.TileLayer('stamenterrain').add_to(map_)
folium.TileLayer('cartodbdark_matter').add_to(map_)
folium.LayerControl().add_to(map_)
minimap = plugins.MiniMap()
_ = map_.add_child(minimap)
# _
Ahora agregamos las estaciones usando la siguiente función
def plot_station(row):
'''input: series that contains a numeric named latitude and a numeric named longitude
this function creates a CircleMarker and adds it to your this_map'''
html = row.to_frame("_").to_html(classes="table table-striped table-hover table-condensed table-responsive")
popup = folium.Popup(html, max_width=2650)
folium.Marker(location=[row.latitud, row.longitud], popup=popup).add_to(marker_cluster)
df_cat.apply(plot_station, axis=1)
map_
